package com.ruoyi.spin.task;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.google.common.base.Stopwatch;
import com.ruoyi.common.config.RedisKeys;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DingUtil;
import com.ruoyi.common.utils.RedisUtil;
import com.ruoyi.spin.domain.SpinCoinBean;
import com.ruoyi.spin.domain.resp.DailySpinRspDTO;
import com.ruoyi.spin.service.ISpinCoinBeanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 检查 DailyApi 接口数据是否正常
 *
 * @author lorry
 * @date 2023-1-13 17:43:37
 */
@Component("dailyApiCheckTask")
@Slf4j
public class DailyAPICheckTask {
  private static final Map<String, String> HEADER_MAP = new HashMap<>(8);

  static {
    HEADER_MAP.put(
        "Accept",
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
    HEADER_MAP.put("Accept-Encoding", "gzip, deflate");
    HEADER_MAP.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
    HEADER_MAP.put("Cache-Control", "max-age=0");
    HEADER_MAP.put("Connection", "keep-alive");
    HEADER_MAP.put(
        "User-Agent",
        "Mozilla/5.0 (Linux; Android 9; SM-A105M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36");
  }

  String spin3url = "https://ap.spinmasterfree.com/ap/daily-reward";
  String spin1url = "http://128.199.174.32/api/spins";

  @Autowired private RuoYiConfig ruoYiConfig;
  @Autowired private ISpinCoinBeanService spinCoinBeanService;
  @Autowired private RedisUtil redisUtil;

  public void checkSpin3() {
    Stopwatch stopwatch = Stopwatch.createStarted();
    log.info("checkSpin3 start...");

    HttpRequest request = HttpRequest.get(spin3url);
    request.addHeaders(HEADER_MAP);
    HttpResponse response = request.execute();

    if (response.getStatus() == HttpStatus.HTTP_OK) {
      String body = response.body();
      log.info("checkSpin3 result: {}", JSONUtil.toJsonStr(body));

      DailySpinRspDTO dailySpinRspDTO = JSONUtil.toBean(body, DailySpinRspDTO.class);
      if (!Objects.equals(dailySpinRspDTO.getCode(), HttpStatus.HTTP_OK)) {
        DingUtil.sendText("Daily-API-Check is error! plz check now!!!");
      }

      List<DailySpinRspDTO.DataDTO> data = dailySpinRspDTO.getData();
      if (CollectionUtils.isEmpty(data)) {
        DingUtil.sendText("Daily-API-Check is error! plz check now!!!");
      }

      // 对比源数据接口是否有新数据未获取到
      List<DailySpinRspDTO.DataDTO.RewardsDTO> rewardsDTOList = new ArrayList<>();
      for (DailySpinRspDTO.DataDTO datum : data) {
        rewardsDTOList.addAll(datum.getRewards());
      }
      Map<String, DailySpinRspDTO.DataDTO.RewardsDTO> rewardMap =
          rewardsDTOList.stream()
              .collect(
                  Collectors.toMap(
                      DailySpinRspDTO.DataDTO.RewardsDTO::getTke, Function.identity()));

      SpinCoinBean bean = new SpinCoinBean();
      bean.setCreatedTimeAfter(DateUtils.getLastDay(3));
      // 最近3天的数据
      List<SpinCoinBean> spinCoinBeans = spinCoinBeanService.selectSpinCoinBeanList(bean);
      if (!CollectionUtils.isEmpty(spinCoinBeans)) {
        Map<String, SpinCoinBean> originMap =
            spinCoinBeans.stream()
                .collect(Collectors.toMap(SpinCoinBean::getToken, Function.identity()));
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, DailySpinRspDTO.DataDTO.RewardsDTO> entry : rewardMap.entrySet()) {
          if (!originMap.containsKey(entry.getKey())) {
            sb.append(entry.getKey()).append("\n");
          } else {
            System.out.println("存在entry = " + entry);
          }
        }

        int count = 0;
        if (redisUtil.hHasKey(RedisKeys.getDayMapKey(3), DateUtils.getDate())) {
          count = (int) redisUtil.hget(RedisKeys.getDayMapKey(3), DateUtils.getDate());
        }
        if (StrUtil.isNotEmpty(sb.toString()) && count <= 3) {
          DingUtil.sendText("Daily-API-Check oops, 有新数据未更新！\n".concat(sb.toString()));

          redisUtil.hincr(RedisKeys.getDayMapKey(3), DateUtils.getDate(), 1);
          redisUtil.hdel(RedisKeys.getHourMapKey(3), DateUtils.getLastDay(1));
        }
      } else {
        DingUtil.sendText("Daily-API-Check 源数据表里没有数据！");
      }

      // 检测当天第一天如在18点以后还未获取到则预警
      if (DateUtils.isAfter(ruoYiConfig.getCheckStartTime())) {
        boolean haveTodayData =
            data.stream().anyMatch(m -> m.getDate().equals(DateUtils.getDate()));
        int count = 0;
        if (redisUtil.hHasKey(RedisKeys.getHourMapKey(3), DateUtils.getDateHour())) {
          count = (int) redisUtil.hget(RedisKeys.getHourMapKey(3), DateUtils.getDateHour());
        }
        if (!haveTodayData && count <= 3) {
          DingUtil.sendText("Daily-API-Check 今天还没有数据，快点检查下！");
          redisUtil.hincr(RedisKeys.getHourMapKey(3), DateUtils.getDateHour(), 1);
          redisUtil.hset(RedisKeys.getHourMapKey(3), DateUtils.getLastHour(2), 0);
        }
      }
    }

    log.info("checkSpin3 end, elapsed time: {}", stopwatch.elapsed(TimeUnit.MILLISECONDS));
  }

  public void checkSpin1() {
    Stopwatch stopwatch = Stopwatch.createStarted();
    log.info("checkSpin3 start...");

    HttpRequest request = HttpRequest.get(spin1url);
    request.addHeaders(HEADER_MAP);
    HttpResponse response = request.execute();

    if (response.getStatus() == HttpStatus.HTTP_OK) {
      String body = response.body();
      log.info("checkSpin1 result: {}", JSONUtil.toJsonStr(body));

      DailySpinRspDTO dailySpinRspDTO = JSONUtil.toBean(body, DailySpinRspDTO.class);
      if (!Objects.equals(dailySpinRspDTO.getCode(), HttpStatus.HTTP_OK)) {
        DingUtil.sendText("Daily-API-Check is error! plz check now!!!");
      }

      List<DailySpinRspDTO.DataDTO> data = dailySpinRspDTO.getData();
      if (CollectionUtils.isEmpty(data)) {
        DingUtil.sendText("Daily-API-Check is error! plz check now!!!");
      }

      if (DateUtils.isAfter(ruoYiConfig.getCheckStartTime())) {
        boolean haveTodayData =
            data.stream().anyMatch(m -> m.getDate().equals(DateUtils.getDate()));
        Integer count =
            (Integer) redisUtil.hget(RedisKeys.getHourMapKey(1), DateUtils.getDateHour());
        if (!haveTodayData && count <= 3) {
          DingUtil.sendText("Daily-API-Check 今天还没有数据，快点检查下！");
          redisUtil.hincr(RedisKeys.getHourMapKey(1), DateUtils.getDateHour(), 1);
          redisUtil.hset(RedisKeys.getHourMapKey(1), DateUtils.getLastHour(2), 0);
        }
      }

      List<SpinCoinBean> spinCoinBeans =
          spinCoinBeanService.selectSpinCoinBeanList(new SpinCoinBean());
      if (!CollectionUtils.isEmpty(spinCoinBeans)) {
        Map<String, SpinCoinBean> originMap =
            spinCoinBeans.stream()
                .collect(Collectors.toMap(SpinCoinBean::getToken, Function.identity()));

        List<DailySpinRspDTO.DataDTO.RewardsDTO> rewardsDTOList = new ArrayList<>();
        for (DailySpinRspDTO.DataDTO datum : data) {
          rewardsDTOList.addAll(datum.getRewards());
        }
        Map<String, DailySpinRspDTO.DataDTO.RewardsDTO> rewardMap =
            rewardsDTOList.stream()
                .collect(
                    Collectors.toMap(
                        DailySpinRspDTO.DataDTO.RewardsDTO::getTke, Function.identity()));

        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, SpinCoinBean> entry : originMap.entrySet()) {
          if (!rewardMap.containsKey(entry.getKey())) {
            sb.append(entry.getKey()).append("\t");
          }
        }

        Integer count = (Integer) redisUtil.hget(RedisKeys.getDayMapKey(1), DateUtils.getDate());
        if (StrUtil.isNotEmpty(sb.toString()) && count <= 5) {
          DingUtil.sendText("Daily-API-Check oops, 这么久还没数据！\n".concat(sb.toString()));

          redisUtil.hincr(RedisKeys.getDayMapKey(1), DateUtils.getDate(), 1);
          redisUtil.hdel(RedisKeys.getHourMapKey(1), DateUtils.getLastDay(1));
        }
      } else {
        DingUtil.sendText("Daily-API-Check 源数据表里没有数据！");
      }
    }

    log.info("checkSpin1 end, elapsed time: {}", stopwatch.elapsed(TimeUnit.MILLISECONDS));
  }
}
